/*
* Copyright 2011 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/
package org.etherframework.dependency
{
	import org.etherframework.IEther;
	import org.etherframework.common.Access;
	import org.etherframework.common.dependency.IEtherChild;
	import org.etherframework.common.dependency.IEtherOwner;
	import org.etherframework.common.dependency.facade.IDependenciesFacade;
	import org.etherframework.controller.EtherCommand;
	import org.etherframework.core.bridge.IBridgeFacades;
	import org.etherframework.core.common.Ether;
	import org.etherframework.core.common.EtherTypes;
	import org.etherframework.core.common.ether_internal;
	import org.etherframework.core.module.IModulePartFacade;

	public class DependenciesFacade implements IDependenciesFacade
	{
		private static var _ether:IEther;
		
		private var _owner:IBridgeFacades;
		private var _part:IDependencies;
		
		public function DependenciesFacade(owner:IBridgeFacades, part:IDependencies)
		{
			_owner = owner;
			_part = part;
		}
		
		public function prepare(ether:IEther):IModulePartFacade
		{
			_ether = ether;
			
			return this;
		}
		
		public function getInstance(asked:Class):*
		{
			if (!asked)
				return null;
			
			if (EtherTypes.isUnsupported(asked))
				throw new Error("Type " + asked + " is not supported.");
			
			var result:Object;
			const e:Ether = _ether as Ether;
			
			if (_owner.access == Access.GLOBAL)
			{
				result = _owner.parent.contextual(_owner.context).dependencies.getInstance(asked);
			}
			else
			{
				result = _part.contextual(_owner.context).getDependency(asked);
				
				if (!result && _owner.parent)
					return _owner.parent.contextual(_owner.context).dependencies.getInstance(asked);
			}
			
			if (!result)
				throw new Error("Dependency for " + asked + " could not be found. " +
					"Please, make sure that it was added to module dependencies.");
			
			result = result is Dependency ? 
				result.getInstance(_ether ? _ether.context : null) : result;
			
			if (e && (result is IEtherChild) && 
				(e.ether_internal::_target is IEtherOwner))
			{
				IEtherChild(result).owner(e.ether_internal::_target as IEtherOwner);
			}
			
			_ether = null
			return result;
		}
	}
}